home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / uucp-104.lha / uucp-1.04 / uucico.c < prev    next >
C/C++ Source or Header  |  1993-02-13  |  66KB  |  2,619 lines

  1. /* uucico.c
  2.    This is the main UUCP communication program.
  3.  
  4.    Copyright (C) 1991, 1992 Ian Lance Taylor
  5.  
  6.    This file is part of the Taylor UUCP package.
  7.  
  8.    This program is free software; you can redistribute it and/or
  9.    modify it under the terms of the GNU General Public License as
  10.    published by the Free Software Foundation; either version 2 of the
  11.    License, or (at your option) any later version.
  12.  
  13.    This program is distributed in the hope that it will be useful, but
  14.    WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.    General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22.    The author of the program may be contacted at ian@airs.com or
  23.    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
  24.    */
  25.  
  26. #include "uucp.h"
  27.  
  28. #if USE_RCS_ID
  29. const char uucico_rcsid[] = "$Id: uucico.c,v 1.140 1993/01/18 05:03:06 ian Rel $";
  30. #endif
  31.  
  32. #include <ctype.h>
  33.  
  34. #if HAVE_LIMITS_H
  35. #include <limits.h>
  36. #else
  37. #define LONG_MAX 2147483647L
  38. #endif
  39.  
  40. #include "getopt.h"
  41.  
  42. #include "uudefs.h"
  43. #include "uuconf.h"
  44. #include "conn.h"
  45. #include "prot.h"
  46. #include "trans.h"
  47. #include "system.h"
  48.  
  49. /* The program name.  */
  50. char abProgram[] = "uucico";
  51.  
  52. /* Define the known protocols.  */
  53.  
  54. #define TCP_PROTO \
  55.   (UUCONF_RELIABLE_ENDTOEND \
  56.    | UUCONF_RELIABLE_RELIABLE \
  57.    | UUCONF_RELIABLE_EIGHT)
  58.  
  59. static const struct sprotocol asProtocols[] =
  60. {
  61.   { 't', TCP_PROTO, 1,
  62.       asTproto_params, ftstart, ftshutdown, ftsendcmd, ztgetspace,
  63.       ftsenddata, ftwait, ftfile },
  64.   { 'e', TCP_PROTO, 1,
  65.       asEproto_params, festart, feshutdown, fesendcmd, zegetspace,
  66.       fesenddata, fewait, fefile },
  67.   { 'i', UUCONF_RELIABLE_EIGHT, 7,
  68.       asIproto_params, fistart, fishutdown, fisendcmd, zigetspace,
  69.       fisenddata, fiwait, NULL },
  70.   { 'a', UUCONF_RELIABLE_EIGHT, 1,
  71.       asZproto_params, fzstart, fzshutdown, fzsendcmd, zzgetspace,
  72.       fzsenddata, fzwait, fzfile },
  73.   { 'g', UUCONF_RELIABLE_EIGHT, 1,
  74.       asGproto_params, fgstart, fgshutdown, fgsendcmd, zggetspace,
  75.       fgsenddata, fgwait, NULL },
  76.   { 'G', UUCONF_RELIABLE_EIGHT, 1,
  77.       asGproto_params, fbiggstart, fgshutdown, fgsendcmd, zggetspace,
  78.       fgsenddata, fgwait, NULL },
  79.   { 'j', UUCONF_RELIABLE_EIGHT, 7,
  80.       asIproto_params, fjstart, fjshutdown, fisendcmd, zigetspace,
  81.       fisenddata, fiwait, NULL },
  82.   { 'f', UUCONF_RELIABLE_RELIABLE, 1,
  83.       asFproto_params, ffstart, ffshutdown, ffsendcmd, zfgetspace,
  84.       ffsenddata, ffwait, fffile },
  85. };
  86.  
  87. #define CPROTOCOLS (sizeof asProtocols / sizeof asProtocols[0])
  88.  
  89. /* Locked system.  */
  90. static boolean fLocked_system;
  91. static struct uuconf_system sLocked_system;
  92.  
  93. /* Daemon structure holding information about the remote system (must
  94.    be global so the error handler can see it.  */
  95. static struct sdaemon sDaemon;
  96.  
  97. /* Open connection.  */
  98. static struct sconnection *qConn;
  99.  
  100. /* uuconf global pointer; need to close the connection after a fatal
  101.    error.  */
  102. static pointer pUuconf;
  103.  
  104. /* This structure is passed to iuport_lock via uuconf_find_port.  */
  105. struct spass
  106. {
  107.   boolean fmatched;
  108.   boolean flocked;
  109.   struct sconnection *qconn;
  110. };
  111.  
  112. /* Local functions.  */
  113.  
  114. static void uusage P((void));
  115. static void uabort P((void));
  116. static boolean fcall P((pointer puuconf,
  117.             const struct uuconf_system *qsys,
  118.             struct uuconf_port *qport, boolean fifwork,
  119.             boolean fforce, boolean fdetach,
  120.             boolean ftimewarn));
  121. static boolean fconn_call P((struct sdaemon *qdaemon,
  122.                  struct uuconf_port *qport,
  123.                  struct sstatus *qstat, int cretry,
  124.                  boolean *pfcalled));
  125. static boolean fdo_call P((struct sdaemon *qdaemon,
  126.                struct sstatus *qstat,
  127.                const struct uuconf_dialer *qdialer,
  128.                boolean *pfcalled, enum tstatus_type *pterr));
  129. static int iuport_lock P((struct uuconf_port *qport, pointer pinfo));
  130. static boolean flogin_prompt P((pointer puuconf,
  131.                 struct sconnection *qconn));
  132. static boolean faccept_call P((pointer puuconf, const char *zlogin,
  133.                    struct sconnection *qconn,
  134.                    const char **pzsystem));
  135. static void uapply_proto_params P((pointer puuconf, int bproto,
  136.                    struct uuconf_cmdtab *qcmds,
  137.                    struct uuconf_proto_param *pas));
  138. static boolean fsend_uucp_cmd P((struct sconnection *qconn,
  139.                  const char *z));
  140. static char *zget_uucp_cmd P((struct sconnection *qconn,
  141.                   boolean frequired));
  142. static char *zget_typed_line P((struct sconnection *qconn));
  143.  
  144. /* Long getopt options.  */
  145. static const struct option asLongopts[] = { { NULL, 0, NULL, 0 } };
  146.  
  147. int
  148. main (argc, argv)
  149.      int argc;
  150.      char **argv;
  151. {
  152.   /* -c: Whether to warn if a call is attempted at a bad time.  */
  153.   boolean ftimewarn = TRUE;
  154.   /* -D: don't detach from controlling terminal.  */
  155.   boolean fdetach = TRUE;
  156.   /* -e: Whether to do an endless loop of accepting calls.  */
  157.   boolean fendless = FALSE;
  158.   /* -f: Whether to force a call despite status of previous call.  */
  159.   boolean fforce = FALSE;
  160.   /* -I file: configuration file name.  */
  161.   const char *zconfig = NULL;
  162.   /* -l: Whether to give a single login prompt.  */
  163.   boolean flogin = FALSE;
  164.   /* -P port: port to use; in master mode, call out on this port.  In
  165.      slave mode, accept logins on this port.  If port not specified,
  166.      then in master mode figure it out for each system, and in slave
  167.      mode use stdin and stdout.  */
  168.   const char *zport = NULL;
  169.   /* -q: Whether to start uuxqt when done.  */
  170.   boolean fuuxqt = TRUE;
  171.   /* -r1: Whether we are the master.  */
  172.   boolean fmaster = FALSE;
  173.   /* -s,-S system: system to call.  */
  174.   const char *zsystem = NULL;
  175.   /* -w: Whether to wait for a call after doing one.  */
  176.   boolean fwait = FALSE;
  177.   int iopt;
  178.   struct uuconf_port *qport;
  179.   struct uuconf_port sport;
  180.   boolean fret = TRUE;
  181.   pointer puuconf;
  182.   int iuuconf;
  183. #if DEBUG > 1
  184.   int iholddebug;
  185. #endif
  186.  
  187.   while ((iopt = getopt_long (argc, argv,
  188.                   "cDefI:lp:qr:s:S:u:x:X:w",
  189.                   asLongopts, (int *) NULL)) != EOF)
  190.     {
  191.       switch (iopt)
  192.     {
  193.     case 'c':
  194.       /* Don't warn if a call is attempted at a bad time.  */
  195.       ftimewarn = FALSE;
  196.       break;
  197.  
  198.     case 'D':
  199.       /* Don't detach from controlling terminal.  */
  200.       fdetach = FALSE;
  201.       break;
  202.  
  203.     case 'e':
  204.       /* Do an endless loop of accepting calls.  */
  205.       fendless = TRUE;
  206.       break;
  207.  
  208.     case 'f':
  209.       /* Force a call even if it hasn't been long enough since the last
  210.          failed call.  */
  211.       fforce = TRUE;
  212.       break;
  213.  
  214.     case 'I':
  215.       /* Set configuration file name (default is in sysdep.h).  */
  216.       if (fsysdep_other_config (optarg))
  217.         zconfig = optarg;
  218.       break;
  219.  
  220.     case 'l':
  221.       /* Prompt for login name and password.  */
  222.       flogin = TRUE;
  223.       break;
  224.  
  225.     case 'p':
  226.       /* Port to use  */
  227.       zport = optarg;
  228.       break;
  229.  
  230.     case 'q':
  231.       /* Don't start uuxqt.  */
  232.       fuuxqt = FALSE;
  233.       break;
  234.  
  235.     case 'r':
  236.       /* Set mode: -r1 for master, -r0 for slave (default)  */
  237.       if (strcmp (optarg, "1") == 0)
  238.         fmaster = TRUE;
  239.       else if (strcmp (optarg, "0") == 0)
  240.         fmaster = FALSE;
  241.       else
  242.         uusage ();
  243.       break;
  244.     
  245.     case 's':
  246.       /* Set system name  */
  247.       zsystem = optarg;
  248.       fmaster = TRUE;
  249.       break;
  250.  
  251.     case 'S':
  252.       /* Set system name and force call like -f  */
  253.       zsystem = optarg;
  254.       fforce = TRUE;
  255.       fmaster = TRUE;
  256.       break;
  257.  
  258.     case 'u':
  259.       /* Some versions of uucpd invoke uucico with a -u argument
  260.          specifying the login name.  I'm told it is safe to ignore
  261.          this value, although perhaps we should use it rather than
  262.          zsysdep_login_name ().  */
  263.       break;
  264.  
  265.     case 'x':
  266.     case 'X':
  267. #if DEBUG > 1
  268.       /* Set debugging level  */
  269.       iDebug |= idebug_parse (optarg);
  270. #endif
  271.       break;
  272.  
  273.     case 'w':
  274.       /* Call out and then wait for a call in  */
  275.       fwait = TRUE;
  276.       break;
  277.  
  278.     case 0:
  279.       /* Long option found, and flag value set.  */
  280.       break;
  281.  
  282.     default:
  283.       uusage ();
  284.       break;
  285.     }
  286.     }
  287.  
  288.   if (optind != argc)
  289.     uusage ();
  290.  
  291.   if (fwait && zport == NULL)
  292.     {
  293.       ulog (LOG_ERROR, "-w requires -e");
  294.       uusage ();
  295.     }
  296.  
  297.   iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
  298.   if (iuuconf != UUCONF_SUCCESS)
  299.     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
  300.   pUuconf = puuconf;
  301.  
  302. #if DEBUG > 1
  303.   {
  304.     const char *zdebug;
  305.  
  306.     iuuconf = uuconf_debuglevel (puuconf, &zdebug);
  307.     if (iuuconf != UUCONF_SUCCESS)
  308.       ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
  309.     if (zdebug != NULL)
  310.       iDebug |= idebug_parse (zdebug);
  311.   }
  312. #endif
  313.  
  314.   /* If a port was named, get its information.  */
  315.   if (zport == NULL)
  316.     qport = NULL;
  317.   else
  318.     {
  319.       iuuconf = uuconf_find_port (puuconf, zport, (long) 0, (long) 0,
  320.                   (int (*) P((struct uuconf_port *,
  321.                           pointer))) NULL,
  322.                   (pointer) NULL, &sport);
  323.       if (iuuconf == UUCONF_NOT_FOUND)
  324.     ulog (LOG_FATAL, "%s: Port not found", zport);
  325.       else if (iuuconf != UUCONF_SUCCESS)
  326.     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
  327.       qport = &sport;
  328.     }
  329.  
  330. #ifdef SIGINT
  331.   usysdep_signal (SIGINT);
  332. #endif
  333. #ifdef SIGHUP
  334.   usysdep_signal (SIGHUP);
  335. #endif
  336. #ifdef SIGQUIT
  337.   usysdep_signal (SIGQUIT);
  338. #endif
  339. #ifdef SIGTERM
  340.   usysdep_signal (SIGTERM);
  341. #endif
  342. #ifdef SIGPIPE
  343.   usysdep_signal (SIGPIPE);
  344. #endif
  345.  
  346.   usysdep_initialize (puuconf, INIT_SUID);
  347.  
  348.   ulog_to_file (puuconf, TRUE);
  349.   ulog_fatal_fn (uabort);
  350.  
  351.   if (fmaster)
  352.     {
  353.       if (zsystem != NULL)
  354.     {
  355.       /* A system was named.  Call it.  */
  356.       iuuconf = uuconf_system_info (puuconf, zsystem,
  357.                     &sLocked_system);
  358.       if (iuuconf == UUCONF_NOT_FOUND)
  359.         ulog (LOG_FATAL, "%s: System not found", zsystem);
  360.       else if (iuuconf != UUCONF_SUCCESS)
  361.         ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
  362.  
  363.       /* Detach from the controlling terminal for the call.  This
  364.          probably makes sense only on Unix.  We want the modem
  365.          line to become the controlling terminal.  */
  366.       if (fdetach &&
  367.           (qport == NULL
  368.            || qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN))
  369.         usysdep_detach ();
  370.  
  371.       ulog_system (sLocked_system.uuconf_zname);
  372.  
  373. #if DEBUG > 1
  374.       iholddebug = iDebug;
  375.       if (sLocked_system.uuconf_zdebug != NULL)
  376.         iDebug |= idebug_parse (sLocked_system.uuconf_zdebug);
  377. #endif
  378.  
  379.       if (! fsysdep_lock_system (&sLocked_system))
  380.         {
  381.           ulog (LOG_ERROR, "System already locked");
  382.           fret = FALSE;
  383.         }
  384.       else
  385.         {
  386.           fLocked_system = TRUE;
  387.           fret = fcall (puuconf, &sLocked_system, qport, FALSE,
  388.                 fforce, fdetach, ftimewarn);
  389.           if (fLocked_system)
  390.         {
  391.           (void) fsysdep_unlock_system (&sLocked_system);
  392.           fLocked_system = FALSE;
  393.         }
  394.         }
  395. #if DEBUG > 1
  396.       iDebug = iholddebug;
  397. #endif
  398.       ulog_system ((const char *) NULL);
  399.       (void) uuconf_system_free (puuconf, &sLocked_system);
  400.     }
  401.       else
  402.     {
  403.       char **pznames, **pz;
  404.       int c, i;
  405.       boolean fdidone;
  406.  
  407.       /* Call all systems which have work to do.  */
  408.       fret = TRUE;
  409.       fdidone = FALSE;
  410.  
  411.       iuuconf = uuconf_system_names (puuconf, &pznames, 0);
  412.       if (iuuconf != UUCONF_SUCCESS)
  413.         ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
  414.  
  415.       /* Randomize the order in which we call the systems.  */
  416.       c = 0;
  417.       for (pz = pznames; *pz != NULL; pz++)
  418.         c++;
  419.  
  420.       srand ((unsigned int) ixsysdep_time ((long *) NULL));
  421.       for (i = c - 1; i > 0; i--)
  422.         {
  423.           int iuse;
  424.           char *zhold;
  425.  
  426.           iuse = rand () % (i + 1);
  427.           zhold = pznames[i];
  428.           pznames[i] = pznames[iuse];
  429.           pznames[iuse] = zhold;
  430.         }
  431.  
  432.       for (pz = pznames; *pz != NULL && ! FGOT_SIGNAL (); pz++)
  433.         {
  434.           iuuconf = uuconf_system_info (puuconf, *pz,
  435.                         &sLocked_system);
  436.           if (iuuconf != UUCONF_SUCCESS)
  437.         {
  438.           ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  439.           xfree ((pointer) *pz);
  440.           continue;
  441.         }
  442.  
  443.           if (fsysdep_has_work (&sLocked_system))
  444.         {
  445.           fdidone = TRUE;
  446.  
  447.           /* Detach from the controlling terminal.  On Unix
  448.              this means that we will wind up forking a new
  449.              process for each system we call.  */
  450.           if (fdetach
  451.               && (qport == NULL
  452.               || qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN))
  453.             usysdep_detach ();
  454.  
  455.           ulog_system (sLocked_system.uuconf_zname);
  456.  
  457. #if DEBUG > 1
  458.           iholddebug = iDebug;
  459.           if (sLocked_system.uuconf_zdebug != NULL)
  460.             iDebug |= idebug_parse (sLocked_system.uuconf_zdebug);
  461. #endif
  462.  
  463.           if (! fsysdep_lock_system (&sLocked_system))
  464.             {
  465.               ulog (LOG_ERROR, "System already locked");
  466.               fret = FALSE;
  467.             }
  468.           else
  469.             {
  470.               fLocked_system = TRUE;
  471.               if (! fcall (puuconf, &sLocked_system, qport, TRUE,
  472.                    fforce, fdetach, ftimewarn))
  473.             fret = FALSE;
  474.  
  475.               /* Now ignore any SIGHUP that we got.  */
  476.               afSignal[INDEXSIG_SIGHUP] = FALSE;
  477.  
  478.               if (fLocked_system)
  479.             {
  480.               (void) fsysdep_unlock_system (&sLocked_system);
  481.               fLocked_system = FALSE;
  482.             }
  483.             }
  484. #if DEBUG > 1
  485.           iDebug = iholddebug;
  486. #endif
  487.           ulog_system ((const char *) NULL);
  488.         }
  489.  
  490.           (void) uuconf_system_free (puuconf, &sLocked_system);
  491.           xfree ((pointer) *pz);
  492.         }
  493.  
  494.       xfree ((pointer) pznames);
  495.  
  496.       if (! fdidone)
  497.         ulog (LOG_NORMAL, "No work");
  498.     }
  499.  
  500.       /* If requested, wait for calls after dialing out.  */
  501.       if (fwait)
  502.     {
  503.       fendless = TRUE;
  504.       fmaster = FALSE;
  505.     }
  506.     }
  507.  
  508.   if (! fmaster)
  509.     {
  510.       struct sconnection sconn;
  511.       boolean flocked;
  512.  
  513.       /* If a port was specified by name, we go into endless loop
  514.      mode.  In this mode, we wait for calls and prompt them with
  515.      "login:" and "Password:", so that they think we are a regular
  516.      UNIX system.  If we aren't in endless loop mode, we have been
  517.      called by some other system.  If flogin is TRUE, we prompt
  518.      with "login:" and "Password:" a single time.  */
  519.  
  520.       fret = TRUE;
  521.       zsystem = NULL;
  522.  
  523.       if (! fconn_init (qport, &sconn))
  524.     fret = FALSE;
  525.  
  526.       if (qport != NULL)
  527.     {
  528.       /* We are not using standard input.  Detach from the
  529.          controlling terminal, so that the port we are about to
  530.          use becomes our controlling terminal.  */
  531.       if (fdetach
  532.           && qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN)
  533.         usysdep_detach ();
  534.  
  535.       /* If a port was given, we loop forever.  */
  536.       fendless = TRUE;
  537.     }
  538.  
  539.       if (fconn_lock (&sconn, TRUE))
  540.     flocked = TRUE;
  541.       else
  542.     {
  543.       flocked = FALSE;
  544.       ulog (LOG_ERROR, "%s: Port already locked",
  545.         qport->uuconf_zname);
  546.       fret = FALSE;
  547.     }
  548.  
  549.       if (fret)
  550.     {
  551.       if (! fconn_open (&sconn, (long) 0, (long) 0, TRUE))
  552.         fret = FALSE;
  553.       qConn = &sconn;
  554.     }
  555.  
  556.       if (fret)
  557.     {
  558.       if (fendless)
  559.         {
  560.           while (! FGOT_SIGNAL ()
  561.              && flogin_prompt (puuconf, &sconn))
  562.         {
  563.           /* Now ignore any SIGHUP that we got.  */
  564.           afSignal[INDEXSIG_SIGHUP] = FALSE;
  565.  
  566.           if (fLocked_system)
  567.             {
  568.               (void) fsysdep_unlock_system (&sLocked_system);
  569.               fLocked_system = FALSE;
  570.             }
  571.           if (! fconn_reset (&sconn))
  572.             break;
  573.         }
  574.           fret = FALSE;
  575.         }
  576.       else
  577.         {
  578.           if (flogin)
  579.         fret = flogin_prompt (puuconf, &sconn);
  580.           else
  581.         {
  582. #if DEBUG > 1
  583.           iholddebug = iDebug;
  584. #endif
  585.           fret = faccept_call (puuconf, zsysdep_login_name (),
  586.                        &sconn, &zsystem);
  587. #if DEBUG > 1
  588.           iDebug = iholddebug;
  589. #endif
  590.         }
  591.         }
  592.     }
  593.  
  594.       if (qConn != NULL)
  595.     {
  596.       if (! fconn_close (&sconn, puuconf, (struct uuconf_dialer *) NULL,
  597.                  fret))
  598.         fret = FALSE;
  599.       qConn = NULL;
  600.     }
  601.  
  602.       if (flocked)
  603.     (void) fconn_unlock (&sconn);
  604.  
  605.       if (fLocked_system)
  606.     {
  607.       (void) fsysdep_unlock_system (&sLocked_system);
  608.       fLocked_system = FALSE;
  609.     }
  610.  
  611.       uconn_free (&sconn);
  612.     }
  613.  
  614.   ulog_close ();
  615.   ustats_close ();
  616.  
  617.   /* If we got a SIGTERM, perhaps because the system is going down,
  618.      don't run uuxqt.  We go ahead and run it for any other signal,
  619.      since I think they indicate more temporary conditions.  */
  620.   if (afSignal[INDEXSIG_SIGTERM])
  621.     fuuxqt = FALSE;
  622.  
  623.   if (fuuxqt)
  624.     {
  625.       /* Detach from the controlling terminal before starting up uuxqt,
  626.      so that it runs as a true daemon.  */
  627.       if (fdetach)
  628.     usysdep_detach ();
  629.       if (zsystem == NULL)
  630.     {
  631.       if (! fsysdep_run ("uuxqt", (const char *) NULL,
  632.                  (const char *) NULL))
  633.         fret = FALSE;
  634.     }
  635.       else
  636.     {
  637.       if (! fsysdep_run ("uuxqt", "-s", zsystem))
  638.         fret = FALSE;
  639.     }
  640.     }
  641.  
  642.   usysdep_exit (fret);
  643.  
  644.   /* Avoid complaints about not returning.  */
  645.   return 0;
  646. }
  647.  
  648. /* Print out a usage message.  */
  649.  
  650. static void
  651. uusage ()
  652. {
  653.   fprintf (stderr,
  654.        "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
  655.        VERSION);
  656.   fprintf (stderr,
  657.        "Usage: uucico [options]\n");
  658.   fprintf (stderr,
  659.        " -s,-S system: Call system (-S implies -f)\n");
  660.   fprintf (stderr,
  661.        " -f: Force call despite system status\n");
  662.   fprintf (stderr,
  663.        " -r state: 1 for master, 0 for slave (default)\n");
  664.   fprintf (stderr,
  665.        " -p port: Specify port (implies -e)\n");
  666.   fprintf (stderr,
  667.        " -l: prompt for login name and password\n");
  668.   fprintf (stderr,
  669.        " -e: Endless loop of login prompts and daemon execution\n");
  670.   fprintf (stderr,
  671.        " -w: After calling out, wait for incoming calls\n");
  672.   fprintf (stderr,
  673.        " -q: Don't start uuxqt when done\n");
  674.   fprintf (stderr,
  675.        " -x,-X debug: Set debugging level\n");
  676. #if HAVE_TAYLOR_CONFIG
  677.   fprintf (stderr,
  678.        " -I file: Set configuration file to use\n");
  679. #endif /* HAVE_TAYLOR_CONFIG */
  680.  
  681.   exit (EXIT_FAILURE);
  682. }
  683.  
  684. /* This function is called when a LOG_FATAL error occurs.  */
  685.  
  686. static void
  687. uabort ()
  688. {
  689.   if (fLocked_system)
  690.     ufailed (&sDaemon);
  691.  
  692.   ulog_user ((const char *) NULL);
  693.  
  694.   if (qConn != NULL)
  695.     {
  696.       (void) fconn_close (qConn, pUuconf, (struct uuconf_dialer *) NULL,
  697.               FALSE);
  698.       (void) fconn_unlock (qConn);
  699.       uconn_free (qConn);
  700.     }
  701.  
  702.   if (fLocked_system)
  703.     {
  704.       (void) fsysdep_unlock_system (&sLocked_system);
  705.       fLocked_system = FALSE;
  706.     }
  707.  
  708.   ulog_system ((const char *) NULL);
  709.  
  710.   ulog_close ();
  711.   ustats_close ();
  712.  
  713.   usysdep_exit (FALSE);
  714. }
  715.  
  716. /* Call another system, trying all the possible sets of calling
  717.    instructions.  The qsys argument is the system to call.  The qport
  718.    argument is the port to use, and may be NULL.  If the fifwork
  719.    argument is TRUE, the call is only placed if there is work to be
  720.    done.  If the fforce argument is TRUE, a call is forced even if not
  721.    enough time has passed since the last failed call.  If the
  722.    ftimewarn argument is TRUE (the normal case), then a warning is
  723.    given if calls are not permitted at this time.  */
  724.  
  725. static boolean
  726. fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
  727.      pointer puuconf;
  728.      const struct uuconf_system *qorigsys;
  729.      struct uuconf_port *qport;
  730.      boolean fifwork;
  731.      boolean fforce;
  732.      boolean fdetach;
  733.      boolean ftimewarn;
  734. {
  735.   struct sstatus sstat;
  736.   long inow;
  737.   boolean fbadtime, fnevertime;
  738.   const struct uuconf_system *qsys;
  739.  
  740.   if (! fsysdep_get_status (qorigsys, &sstat, (boolean *) NULL))
  741.     return FALSE;
  742.  
  743.   /* Make sure it's been long enough since the last failed call, and
  744.      that we haven't exceeded the maximum number of retries.  Even if
  745.      we are over the limit on retries, we permit a call to be made if
  746.      24 hours have passed.  This 24 hour limit is still controlled by
  747.      the retry time.  */
  748.   inow = ixsysdep_time ((long *) NULL);
  749.   if (! fforce)
  750.     {
  751.       if (qorigsys->uuconf_cmax_retries > 0
  752.       && sstat.cretries >= qorigsys->uuconf_cmax_retries
  753.       && sstat.ilast + 24 * 60 * 60 < inow)
  754.     {
  755.       ulog (LOG_ERROR, "Too many retries");
  756.       return FALSE;
  757.     }
  758.  
  759.       if (sstat.ttype == STATUS_COMPLETE
  760.       ? sstat.ilast + qorigsys->uuconf_csuccess_wait > inow
  761.       : sstat.ilast + sstat.cwait > inow)
  762.     {
  763.       ulog (LOG_NORMAL, "Retry time not reached");
  764.       return FALSE;
  765.     }
  766.     }
  767.  
  768.   sDaemon.puuconf = puuconf;
  769.   sDaemon.qsys = NULL;
  770.   sDaemon.zlocalname = NULL;
  771.   sDaemon.qconn = NULL;
  772.   sDaemon.qproto = NULL;
  773.   sDaemon.clocal_size = -1;
  774.   sDaemon.cremote_size = -1;
  775.   sDaemon.cmax_ever = -2;
  776.   sDaemon.cmax_receive = -1;
  777.   sDaemon.ifeatures = 0;
  778.   sDaemon.frequest_hangup = FALSE;
  779.   sDaemon.fhangup_requested = FALSE;
  780.   sDaemon.fhangup = FALSE;
  781.   sDaemon.fmaster = TRUE;
  782.   sDaemon.fcaller = TRUE;
  783.   sDaemon.ireliable = 0;
  784.   sDaemon.bgrade = '\0';
  785.  
  786.   fbadtime = TRUE;
  787.   fnevertime = TRUE;
  788.  
  789.   for (qsys = qorigsys; qsys != NULL; qsys = qsys->uuconf_qalternate)
  790.     {
  791.       int cretry;
  792.       boolean fany, fret, fcalled;
  793.  
  794.       if (FGOT_SIGNAL ())
  795.     return FALSE;
  796.  
  797.       if (! qsys->uuconf_fcall || qsys->uuconf_qtimegrade == NULL)
  798.     continue;
  799.  
  800.       fnevertime = FALSE;
  801.  
  802.       /* Make sure this is a legal time to call.  */
  803.       if (! ftimespan_match (qsys->uuconf_qtimegrade, (long *) NULL,
  804.                  &cretry))
  805.     continue;
  806.  
  807.       sDaemon.qsys = qsys;
  808.  
  809.       /* Queue up any work there is to do.  */
  810.       if (! fqueue (&sDaemon, &fany))
  811.     return FALSE;
  812.  
  813.       /* If we are only supposed to call if there is work, and there
  814.      isn't any work, check the next alternates.  We can't give up
  815.      at this point because there might be some other alternates
  816.      with fewer restrictions on grade or file transfer size.  */
  817.       if (fifwork && ! fany)
  818.     {
  819.       uclear_queue (&sDaemon);
  820.       continue;
  821.     }
  822.  
  823.       fbadtime = FALSE;
  824.  
  825.       fret = fconn_call (&sDaemon, qport, &sstat, cretry, &fcalled);
  826.  
  827.       uclear_queue (&sDaemon);
  828.  
  829.       if (fret)
  830.     return TRUE;
  831.       if (fcalled)
  832.     return FALSE;
  833.  
  834.       /* Now we have to dump that port so that we can aquire a new
  835.      one.  On Unix this means that we will fork and get a new
  836.      process ID, so we must unlock and relock the system.  */
  837.       if (fdetach)
  838.     {
  839.       (void) fsysdep_unlock_system (&sLocked_system);
  840.       fLocked_system = FALSE;
  841.       usysdep_detach ();
  842.       if (! fsysdep_lock_system (&sLocked_system))
  843.         return FALSE;
  844.       fLocked_system = TRUE;
  845.     }
  846.     }
  847.  
  848.   if (fbadtime && ftimewarn)
  849.     {
  850.       ulog (LOG_NORMAL, "Wrong time to call");
  851.  
  852.       /* Update the status, unless the system can never be called.  If
  853.      the system can never be called, there is little point to
  854.      putting in a ``wrong time to call'' message.  We don't change
  855.      the number of retries, although we do set the wait until the
  856.      next retry to 0.  */
  857.       if (! fnevertime)
  858.     {
  859.       sstat.ttype = STATUS_WRONG_TIME;
  860.       sstat.ilast = inow;
  861.       sstat.cwait = 0;
  862.       (void) fsysdep_set_status (qorigsys, &sstat);
  863.     }
  864.     }
  865.  
  866.   return FALSE;
  867. }
  868.  
  869. /* Find a port to use when calling a system, open a connection, and
  870.    dial the system.  The actual call is done in fdo_call.  This
  871.    routine is responsible for opening and closing the connection.  */
  872.  
  873. static boolean
  874. fconn_call (qdaemon, qport, qstat, cretry, pfcalled)
  875.      struct sdaemon *qdaemon;
  876.      struct uuconf_port *qport;
  877.      struct sstatus *qstat;
  878.      int cretry;
  879.      boolean *pfcalled;
  880. {
  881.   pointer puuconf;
  882.   const struct uuconf_system *qsys;
  883.   struct uuconf_port sport;
  884.   struct sconnection sconn;
  885.   enum tstatus_type terr;
  886.   boolean fret;
  887.  
  888.   puuconf = qdaemon->puuconf;
  889.   qsys = qdaemon->qsys;
  890.  
  891.   *pfcalled = FALSE;
  892.  
  893.   /* Ignore any SIGHUP signal we may have received up to this point.
  894.      This is needed on Unix because we may have gotten one from the
  895.      shell before we detached from the controlling terminal.  */
  896.   afSignal[INDEXSIG_SIGHUP] = FALSE;
  897.  
  898.   /* If no port was specified on the command line, use any port
  899.      defined for the system.  To select the system port: 1) see if
  900.      port information was specified directly; 2) see if a port was
  901.      named; 3) get an available port given the baud rate.  We don't
  902.      change the system status if a port is unavailable; i.e. we don't
  903.      force the system to wait for the retry time.  */
  904.   if (qport == NULL)
  905.     qport = qsys->uuconf_qport;
  906.   if (qport != NULL)
  907.     {
  908.       if (! fconn_init (qport, &sconn))
  909.     return FALSE;
  910.       if (! fconn_lock (&sconn, FALSE))
  911.     {
  912.       ulog (LOG_ERROR, "%s: Port already locked",
  913.         qport->uuconf_zname);
  914.       return FALSE;
  915.     }
  916.     }
  917.   else
  918.     {
  919.       struct spass s;
  920.       int iuuconf;
  921.  
  922.       s.fmatched = FALSE;
  923.       s.flocked = FALSE;
  924.       s.qconn = &sconn;
  925.       iuuconf = uuconf_find_port (puuconf, qsys->uuconf_zport,
  926.                   qsys->uuconf_ibaud,
  927.                   qsys->uuconf_ihighbaud,
  928.                   iuport_lock, (pointer) &s,
  929.                   &sport);
  930.       if (iuuconf == UUCONF_NOT_FOUND)
  931.     {
  932.       if (s.fmatched)
  933.         ulog (LOG_ERROR, "All matching ports in use");
  934.       else
  935.         ulog (LOG_ERROR, "No matching ports");
  936.       return FALSE;
  937.     }
  938.       else if (iuuconf != UUCONF_SUCCESS)
  939.     {
  940.       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  941.       if (s.flocked)
  942.         {
  943.           (void) fconn_unlock (&sconn);
  944.           uconn_free (&sconn);
  945.         }
  946.       return FALSE;
  947.     }
  948.     }
  949.  
  950.   if (! fconn_open (&sconn, qsys->uuconf_ibaud, qsys->uuconf_ihighbaud,
  951.             FALSE))
  952.     {
  953.       terr = STATUS_PORT_FAILED;
  954.       fret = FALSE;
  955.     }
  956.   else
  957.     {
  958.       struct uuconf_dialer *qdialer;
  959.       struct uuconf_dialer sdialer;
  960.       enum tdialerfound tdialer;
  961.  
  962.       if (qsys->uuconf_zalternate == NULL)
  963.     ulog (LOG_NORMAL, "Calling system %s (port %s)", qsys->uuconf_zname,
  964.           zLdevice == NULL ? (char *) "unknown" : zLdevice);
  965.       else
  966.     ulog (LOG_NORMAL, "Calling system %s (alternate %s, port %s)",
  967.           qsys->uuconf_zname, qsys->uuconf_zalternate,
  968.       zLdevice == NULL ? (char *) "unknown" : zLdevice);
  969.  
  970.       qdialer = NULL;
  971.  
  972.       if (! fconn_dial (&sconn, puuconf, qsys, qsys->uuconf_zphone,
  973.             &sdialer, &tdialer))
  974.     {
  975.       terr = STATUS_DIAL_FAILED;
  976.       fret = FALSE;
  977.     }
  978.       else
  979.     {
  980.       qdaemon->qconn = &sconn;
  981.       if (tdialer == DIALERFOUND_FALSE)
  982.         qdialer = NULL;
  983.       else
  984.         qdialer = &sdialer;
  985.       fret = fdo_call (qdaemon, qstat, qdialer, pfcalled, &terr);
  986.     }
  987.  
  988.       (void) fconn_close (&sconn, puuconf, qdialer, fret);
  989.  
  990.       if (tdialer == DIALERFOUND_FREE)
  991.     (void) uuconf_dialer_free (puuconf, &sdialer);
  992.     }
  993.  
  994.   if (! fret)
  995.     {
  996.       DEBUG_MESSAGE2 (DEBUG_HANDSHAKE, "Call failed: %d (%s)",
  997.               (int) terr, azStatus[(int) terr]);
  998.       qstat->ttype = terr;
  999.       qstat->cretries++;
  1000.       qstat->ilast = ixsysdep_time ((long *) NULL);
  1001.       if (cretry == 0)
  1002.     qstat->cwait = CRETRY_WAIT (qstat->cretries);
  1003.       else
  1004.     qstat->cwait = cretry * 60;
  1005.       (void) fsysdep_set_status (qsys, qstat);
  1006.     }
  1007.  
  1008.   (void) fconn_unlock (&sconn);
  1009.   uconn_free (&sconn);
  1010.  
  1011.   if (qport == NULL)
  1012.     (void) uuconf_port_free (puuconf, &sport);
  1013.  
  1014.   return fret;
  1015. }
  1016.  
  1017. /* Do the actual work of calling another system.  The qsys argument is
  1018.    the system to call, the qconn argument is the connection to use,
  1019.    the qstat argument holds the current status of the ssystem, and the
  1020.    qdialer argument holds the dialer being used (it may be NULL).  If
  1021.    we log in successfully, set *pfcalled to TRUE; this is used to
  1022.    distinguish a failed dial from a failure during the call.  If an
  1023.    error occurs *pterr is set to the status type to record.  */
  1024.  
  1025. static boolean
  1026. fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr)
  1027.      struct sdaemon *qdaemon;
  1028.      struct sstatus *qstat;
  1029.      const struct uuconf_dialer *qdialer;
  1030.      boolean *pfcalled;
  1031.      enum tstatus_type *pterr;
  1032. {
  1033.   pointer puuconf;
  1034.   const struct uuconf_system *qsys;
  1035.   struct sconnection *qconn;
  1036.   const char *zport;
  1037.   int iuuconf;
  1038.   char *zstr;
  1039.   long istart_time;
  1040.   char *zlog;
  1041.  
  1042.   puuconf = qdaemon->puuconf;
  1043.   qsys = qdaemon->qsys;
  1044.   qconn = qdaemon->qconn;
  1045.  
  1046.   *pterr = STATUS_LOGIN_FAILED;
  1047.  
  1048.   if (qconn->qport == NULL)
  1049.     zport = "unknown";
  1050.   else
  1051.     zport = qconn->qport->uuconf_zname;
  1052.   if (! fchat (qconn, puuconf, &qsys->uuconf_schat, qsys,
  1053.            (const struct uuconf_dialer *) NULL,
  1054.            (const char *) NULL, FALSE, zport,
  1055.            iconn_baud (qconn)))
  1056.     return FALSE;
  1057.  
  1058.   *pfcalled = TRUE;
  1059.   istart_time = ixsysdep_time ((long *) NULL);
  1060.  
  1061.   *pterr = STATUS_HANDSHAKE_FAILED;
  1062.  
  1063.   /* We should now see "Shere" from the other system.  Newer systems
  1064.      send "Shere=foo" where foo is the remote name.  */
  1065.   zstr = zget_uucp_cmd (qconn, TRUE);
  1066.   if (zstr == NULL)
  1067.     return FALSE;
  1068.  
  1069.   if (strncmp (zstr, "Shere", 5) != 0)
  1070.     {
  1071.       ulog (LOG_ERROR, "Bad initialization string");
  1072.       ubuffree (zstr);
  1073.       return FALSE;
  1074.     }
  1075.  
  1076.   ulog (LOG_NORMAL, "Login successful");
  1077.  
  1078.   qstat->ttype = STATUS_TALKING;
  1079.   qstat->ilast = ixsysdep_time ((long *) NULL);
  1080.   qstat->cretries = 0;
  1081.   qstat->cwait = 0;
  1082.   if (! fsysdep_set_status (qsys, qstat))
  1083.     return FALSE;
  1084.  
  1085.   if (zstr[5] == '=')
  1086.     {
  1087.       const char *zheresys;
  1088.       size_t clen;
  1089.       int icmp;
  1090.  
  1091.       /* Some UUCP packages only provide seven characters in the Shere
  1092.      machine name.  Others only provide fourteen.  */
  1093.       zheresys = zstr + 6;
  1094.       clen = strlen (zheresys);
  1095.       if (clen == 7 || clen == 14)
  1096.     icmp = strncmp (zheresys, qsys->uuconf_zname, clen);
  1097.       else
  1098.     icmp = strcmp (zheresys, qsys->uuconf_zname);
  1099.       if (icmp != 0)
  1100.     {
  1101.       if (qsys->uuconf_pzalias != NULL)
  1102.         {
  1103.           char **pz;
  1104.  
  1105.           for (pz = qsys->uuconf_pzalias; *pz != NULL; pz++)
  1106.         {
  1107.           if (clen == 7 || clen == 14)
  1108.             icmp = strncmp (zheresys, *pz, clen);
  1109.           else
  1110.             icmp = strcmp (zheresys, *pz);
  1111.           if (icmp == 0)
  1112.             break;
  1113.         }
  1114.         }
  1115.       if (icmp != 0)
  1116.         {
  1117.           ulog (LOG_ERROR, "Called wrong system (%s)", zheresys);
  1118.           ubuffree (zstr);
  1119.           return FALSE;
  1120.         }
  1121.     }
  1122.     }
  1123. #if DEBUG > 1
  1124.   else if (zstr[5] != '\0')
  1125.     DEBUG_MESSAGE1 (DEBUG_HANDSHAKE,
  1126.             "fdo_call: Strange Shere: %s", zstr);
  1127. #endif
  1128.  
  1129.   ubuffree (zstr);
  1130.  
  1131.   /* We now send "S" name switches, where name is our UUCP name.  If
  1132.      we are using sequence numbers with this system, we send a -Q
  1133.      argument with the sequence number.  If the call-timegrade command
  1134.      was used, we send a -p argument and a -vgrade= argument with the
  1135.      grade to send us (we send both argument to make it more likely
  1136.      that one is recognized).  We always send a -N (for new) switch
  1137.      indicating what new features we support.  */
  1138.   {
  1139.     long ival;
  1140.     char bgrade;
  1141.     char *zsend;
  1142.     boolean fret;
  1143.  
  1144.     /* Determine the grade we should request of the other system.  A
  1145.        '\0' means that no restrictions have been made.  */
  1146.     if (! ftimespan_match (qsys->uuconf_qcalltimegrade, &ival,
  1147.                (int *) NULL))
  1148.       bgrade = '\0';
  1149.     else
  1150.       bgrade = (char) ival;
  1151.  
  1152.     /* Determine the name we will call ourselves.  */
  1153.     if (qsys->uuconf_zlocalname != NULL)
  1154.       qdaemon->zlocalname = qsys->uuconf_zlocalname;
  1155.     else
  1156.       {
  1157.     iuuconf = uuconf_localname (puuconf, &qdaemon->zlocalname);
  1158.     if (iuuconf == UUCONF_NOT_FOUND)
  1159.       {
  1160.         qdaemon->zlocalname = zsysdep_localname ();
  1161.         if (qdaemon->zlocalname == NULL)
  1162.           return FALSE;
  1163.       }
  1164.     else if (iuuconf != UUCONF_SUCCESS)
  1165.       {
  1166.         ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  1167.         return FALSE;
  1168.       }
  1169.       }        
  1170.  
  1171.     zsend = zbufalc (strlen (qdaemon->zlocalname) + 70);
  1172.     if (! qsys->uuconf_fsequence)
  1173.       {
  1174.     if (bgrade == '\0')
  1175.       sprintf (zsend, "S%s -R -N0%o", qdaemon->zlocalname,
  1176.            (unsigned int) (FEATURE_SIZES
  1177.                    | FEATURE_EXEC
  1178.                    | FEATURE_RESTART));
  1179.     else
  1180.       sprintf (zsend, "S%s -p%c -vgrade=%c -R -N0%o",
  1181.            qdaemon->zlocalname, bgrade, bgrade,
  1182.            (unsigned int) (FEATURE_SIZES
  1183.                    | FEATURE_EXEC
  1184.                    | FEATURE_RESTART));
  1185.       }
  1186.     else
  1187.       {
  1188.     long iseq;
  1189.  
  1190.     iseq = ixsysdep_get_sequence (qsys);
  1191.     if (iseq < 0)
  1192.       return FALSE;
  1193.     if (bgrade == '\0')
  1194.       sprintf (zsend, "S%s -Q%ld -R -N0%o", qdaemon->zlocalname, iseq,
  1195.            (unsigned int) (FEATURE_SIZES
  1196.                    | FEATURE_EXEC
  1197.                    | FEATURE_RESTART));
  1198.     else
  1199.       sprintf (zsend, "S%s -Q%ld -p%c -vgrade=%c -R -N0%o",
  1200.            qdaemon->zlocalname, iseq, bgrade, bgrade,
  1201.            (unsigned int) (FEATURE_SIZES
  1202.                    | FEATURE_EXEC
  1203.                    | FEATURE_RESTART));
  1204.       }
  1205.  
  1206.     fret = fsend_uucp_cmd (qconn, zsend);
  1207.     ubuffree (zsend);
  1208.     if (! fret)
  1209.     return FALSE;
  1210.   }
  1211.  
  1212.   /* Now we should see ROK or Rreason where reason gives a cryptic
  1213.      reason for failure.  If we are talking to a counterpart, we will
  1214.      get back ROKN, possibly with a feature bitfield attached.  */
  1215.   zstr = zget_uucp_cmd (qconn, TRUE);
  1216.   if (zstr == NULL)
  1217.     return FALSE;
  1218.  
  1219.   if (zstr[0] != 'R')
  1220.     {
  1221.       ulog (LOG_ERROR, "Bad reponse to handshake string (%s)",
  1222.         zstr);
  1223.       ubuffree (zstr);
  1224.       return FALSE;
  1225.     }
  1226.  
  1227.   if (strncmp (zstr + 1, "OKN", sizeof "OKN" - 1) == 0)
  1228.     {
  1229.       if (zstr[sizeof "ROKN" - 1] == '\0')
  1230.     qdaemon->ifeatures |= FEATURE_SIZES | FEATURE_V103;
  1231.       else
  1232.     qdaemon->ifeatures |= (int) strtol (zstr + sizeof "ROKN" - 1,
  1233.                        (char **) NULL, 0);
  1234.     }
  1235.   else if (strncmp (zstr + 1, "OK", sizeof "OK" - 1) == 0)
  1236.     {
  1237.       if (zstr[sizeof "ROK" - 1] != '\0')
  1238.     {
  1239.       char *zopt;
  1240.  
  1241.       /* SVR4 UUCP returns options following the ROK string.  */
  1242.       zopt = zstr + sizeof "ROK" - 1;
  1243.       while (*zopt != '\0')
  1244.         {
  1245.           char b;
  1246.           long c;
  1247.           char *zend;
  1248.  
  1249.           b = *zopt++;
  1250.           if (isspace (b) || b != '-')
  1251.         continue;
  1252.           switch (*zopt)
  1253.         {
  1254.         case 'R':
  1255.           qdaemon->ifeatures |= (FEATURE_RESTART
  1256.                      | FEATURE_SVR4
  1257.                      | FEATURE_SIZES);
  1258.           break;
  1259.         case 'U':
  1260.           c = strtol (zopt, &zend, 0);
  1261.           if (c > 0 && c <= LONG_MAX / (long) 512)
  1262.             qdaemon->cmax_receive = c * (long) 512;
  1263.           zopt = zend;
  1264.           break;
  1265.         }
  1266.           while (*zopt != '\0' && ! isspace (*zopt))
  1267.         ++zopt;
  1268.         }
  1269.     }
  1270.     }
  1271.   else if (strcmp (zstr + 1, "CB") == 0)
  1272.     {
  1273.       ulog (LOG_NORMAL, "Remote system will call back");
  1274.       qstat->ttype = STATUS_COMPLETE;
  1275.       (void) fsysdep_set_status (qsys, qstat);
  1276.       ubuffree (zstr);
  1277.       return TRUE;
  1278.     }
  1279.   else
  1280.     {
  1281.       ulog (LOG_ERROR, "Handshake failed (%s)", zstr + 1);
  1282.       ubuffree (zstr);
  1283.       return FALSE;
  1284.     }
  1285.  
  1286.   ubuffree (zstr);
  1287.  
  1288.   /* The slave should now send \020Pprotos\0 where protos is a list of
  1289.      supported protocols.  Each protocol is a single character.  */
  1290.   zstr = zget_uucp_cmd (qconn, TRUE);
  1291.   if (zstr == NULL)
  1292.     return FALSE;
  1293.  
  1294.   if (zstr[0] != 'P')
  1295.     {
  1296.       ulog (LOG_ERROR, "Bad protocol handshake (%s)", zstr);
  1297.       ubuffree (zstr);
  1298.       return FALSE;
  1299.     }
  1300.  
  1301.   /* Determine the reliability characteristics of the connection by
  1302.      combining information for the port and the dialer.  If we have no
  1303.      information, default to a reliable eight-bit full-duplex
  1304.      connection.  */
  1305.   if (qconn->qport != NULL
  1306.       && (qconn->qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
  1307.     qdaemon->ireliable = qconn->qport->uuconf_ireliable;
  1308.   if (qdialer != NULL
  1309.       && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
  1310.     {
  1311.       if (qdaemon->ireliable != 0)
  1312.     qdaemon->ireliable &= qdialer->uuconf_ireliable;
  1313.       else
  1314.     qdaemon->ireliable = qdialer->uuconf_ireliable;
  1315.     }
  1316.   if (qdaemon->ireliable == 0)
  1317.     qdaemon->ireliable = (UUCONF_RELIABLE_RELIABLE
  1318.               | UUCONF_RELIABLE_EIGHT
  1319.               | UUCONF_RELIABLE_FULLDUPLEX
  1320.               | UUCONF_RELIABLE_SPECIFIED);
  1321.  
  1322.   /* Now decide which protocol to use.  The system and the port may
  1323.      have their own list of protocols.  */
  1324.   {
  1325.     int i;
  1326.     char ab[5];
  1327.  
  1328.     i = CPROTOCOLS;
  1329.     if (qsys->uuconf_zprotocols != NULL
  1330.     || (qconn->qport != NULL
  1331.         && qconn->qport->uuconf_zprotocols != NULL))
  1332.       {
  1333.     const char *zproto;
  1334.  
  1335.     if (qsys->uuconf_zprotocols != NULL)
  1336.       zproto = qsys->uuconf_zprotocols;
  1337.     else
  1338.       zproto = qconn->qport->uuconf_zprotocols;
  1339.     for (; *zproto != '\0'; zproto++)
  1340.       {
  1341.         if (strchr (zstr + 1, *zproto) != NULL)
  1342.           {
  1343.         for (i = 0; i < CPROTOCOLS; i++)
  1344.           if (asProtocols[i].bname == *zproto)
  1345.             break;
  1346.         if (i < CPROTOCOLS)
  1347.           break;
  1348.           }
  1349.       }
  1350.       }
  1351.     else
  1352.       {
  1353.     /* If neither the system nor the port specified a list of
  1354.        protocols, we want only protocols that match the known
  1355.        reliability of the dialer and the port.  */
  1356.     for (i = 0; i < CPROTOCOLS; i++)
  1357.       {
  1358.         int ipr;
  1359.  
  1360.         ipr = asProtocols[i].ireliable;
  1361.         if ((ipr & qdaemon->ireliable) != ipr)
  1362.           continue;
  1363.         if (strchr (zstr + 1, asProtocols[i].bname) != NULL)
  1364.           break;
  1365.       }
  1366.       }
  1367.  
  1368.     ubuffree (zstr);
  1369.  
  1370.     if (i >= CPROTOCOLS)
  1371.       {
  1372.     (void) fsend_uucp_cmd (qconn, "UN");
  1373.     ulog (LOG_ERROR, "No mutually supported protocols");
  1374.     return FALSE;
  1375.       }
  1376.  
  1377.     qdaemon->qproto = &asProtocols[i];
  1378.  
  1379.     sprintf (ab, "U%c", qdaemon->qproto->bname);
  1380.     if (! fsend_uucp_cmd (qconn, ab))
  1381.       return FALSE;
  1382.   }
  1383.  
  1384.   /* Run any protocol parameter commands.  */
  1385.   if (qdaemon->qproto->qcmds != NULL)
  1386.     {
  1387.       if (qsys->uuconf_qproto_params != NULL)
  1388.     uapply_proto_params (puuconf, qdaemon->qproto->bname,
  1389.                  qdaemon->qproto->qcmds,
  1390.                  qsys->uuconf_qproto_params);
  1391.       if (qconn->qport != NULL
  1392.       && qconn->qport->uuconf_qproto_params != NULL)
  1393.     uapply_proto_params (puuconf, qdaemon->qproto->bname,
  1394.                  qdaemon->qproto->qcmds,
  1395.                  qconn->qport->uuconf_qproto_params);
  1396.       if (qdialer != NULL
  1397.       && qdialer->uuconf_qproto_params != NULL)
  1398.     uapply_proto_params (puuconf, qdaemon->qproto->bname,
  1399.                  qdaemon->qproto->qcmds,
  1400.                  qdialer->uuconf_qproto_params);
  1401.     }
  1402.  
  1403.   /* Turn on the selected protocol.  */
  1404.   if (! (*qdaemon->qproto->pfstart) (qdaemon, &zlog))
  1405.     return FALSE;
  1406.   if (zlog == NULL)
  1407.     {
  1408.       zlog = zbufalc (sizeof "protocol ''" + 1);
  1409.       sprintf (zlog, "protocol '%c'", qdaemon->qproto->bname);
  1410.     }
  1411.   ulog (LOG_NORMAL, "Handshake successful (%s)", zlog);
  1412.   ubuffree (zlog);
  1413.  
  1414.   *pterr = STATUS_FAILED;
  1415.  
  1416.   {
  1417.     boolean fret;
  1418.     long iend_time;
  1419.  
  1420.     fret = floop (qdaemon);
  1421.  
  1422.     /* Now send the hangup message.  As the caller, we send six O's
  1423.        and expect to receive seven O's.  We send the six O's twice to
  1424.        help the other side.  We don't worry about errors here.  */
  1425.     if (fsend_uucp_cmd (qconn, "OOOOOO")
  1426.     && fsend_uucp_cmd (qconn, "OOOOOO"))
  1427.       {
  1428.     int i, fdone;
  1429.  
  1430.     /* We look for the remote hangup string to ensure that the
  1431.        modem has sent out our hangup string.  This is only
  1432.        necessary because some versions of UUCP complain if they
  1433.        don't get the hangup string.  The remote site should send 7
  1434.        O's, but some versions of UUCP only send 6.  We look for
  1435.        the string several times because supposedly some
  1436.        implementations send some garbage after the last packet but
  1437.        before the hangup string.  */
  1438.     for (i = 0; i < 25; i++)
  1439.       {
  1440.         zstr = zget_uucp_cmd (qconn, FALSE);
  1441.         if (zstr == NULL)
  1442.           break;
  1443.         fdone = strstr (zstr, "OOOOOO") != NULL;
  1444.         ubuffree (zstr);
  1445.         if (fdone)
  1446.           break;
  1447.       }
  1448.       }
  1449.  
  1450.     iend_time = ixsysdep_time ((long *) NULL);
  1451.  
  1452.     ulog (LOG_NORMAL, "Call complete (%ld seconds)",
  1453.       iend_time - istart_time);
  1454.  
  1455.     if (fret)
  1456.       {
  1457.     qstat->ttype = STATUS_COMPLETE;
  1458.     qstat->ilast = iend_time;
  1459.     (void) fsysdep_set_status (qsys, qstat);
  1460.       }
  1461.  
  1462.     return fret;
  1463.   }
  1464. }
  1465.  
  1466. /* This routine is called via uuconf_find_port when a matching port is
  1467.    found.  It tries to lock the port.  If it fails, it returns
  1468.    UUCONF_NOT_FOUND to force uuconf_find_port to continue searching
  1469.    for the next matching port.  */
  1470.  
  1471. static int
  1472. iuport_lock (qport, pinfo)
  1473.      struct uuconf_port *qport;
  1474.      pointer pinfo;
  1475. {
  1476.   struct spass *q = (struct spass *) pinfo;
  1477.  
  1478.   q->fmatched = TRUE;
  1479.  
  1480.   if (! fconn_init (qport, q->qconn))
  1481.     return UUCONF_NOT_FOUND;
  1482.   else if (! fconn_lock (q->qconn, FALSE))
  1483.     {
  1484.       uconn_free (q->qconn);
  1485.       return UUCONF_NOT_FOUND;
  1486.     }
  1487.   else
  1488.     {
  1489.       q->flocked = TRUE;
  1490.       return UUCONF_SUCCESS;
  1491.     }
  1492. }
  1493.  
  1494. /* Prompt for a login name and a password, and run as the slave.  */
  1495.  
  1496. static boolean
  1497. flogin_prompt (puuconf, qconn)
  1498.      pointer puuconf;
  1499.      struct sconnection *qconn;
  1500. {
  1501.   char *zuser, *zpass;
  1502.   boolean fret;
  1503.   int iuuconf;
  1504.  
  1505.   DEBUG_MESSAGE0 (DEBUG_HANDSHAKE, "flogin_prompt: Waiting for login");
  1506.  
  1507.   zuser = NULL;
  1508.   do
  1509.     {
  1510.       ubuffree (zuser);
  1511.       if (! fconn_write (qconn, "login: ", sizeof "login: " - 1))
  1512.     return FALSE;
  1513.       zuser = zget_typed_line (qconn);
  1514.     }
  1515.   while (zuser != NULL && *zuser == '\0');
  1516.  
  1517.   if (zuser == NULL)
  1518.     return TRUE;
  1519.  
  1520.   if (! fconn_write (qconn, "Password:", sizeof "Password:" - 1))
  1521.     {
  1522.       ubuffree (zuser);
  1523.       return FALSE;
  1524.     }
  1525.  
  1526.   zpass = zget_typed_line (qconn);
  1527.   if (zpass == NULL)
  1528.     {
  1529.       ubuffree (zuser);
  1530.       return TRUE;
  1531.     }
  1532.  
  1533.   fret = TRUE;
  1534.  
  1535.   iuuconf = uuconf_callin (puuconf, zuser, zpass);
  1536.   ubuffree (zpass);
  1537.   if (iuuconf == UUCONF_NOT_FOUND)
  1538.     ulog (LOG_ERROR, "Bad login");
  1539.   else if (iuuconf != UUCONF_SUCCESS)
  1540.     {
  1541.       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  1542.       fret = FALSE;
  1543.     }
  1544.   else
  1545.     {
  1546. #if DEBUG > 1
  1547.       int iholddebug;
  1548. #endif
  1549.  
  1550.       /* We ignore the return value of faccept_call because we really
  1551.      don't care whether the call succeeded or not.  We are going
  1552.      to reset the port anyhow.  */
  1553. #if DEBUG > 1
  1554.       iholddebug = iDebug;
  1555. #endif
  1556.       (void) faccept_call (puuconf, zuser, qconn, (const char **) NULL);
  1557. #if DEBUG > 1
  1558.       iDebug = iholddebug;
  1559. #endif
  1560.     }
  1561.  
  1562.   ubuffree (zuser);
  1563.  
  1564.   return fret;
  1565. }
  1566.  
  1567. /* Accept a call from a remote system.  If pqsys is not NULL, *pqsys
  1568.    will be set to the system that called in if known.  */
  1569.  
  1570. static boolean
  1571. faccept_call (puuconf, zlogin, qconn, pzsystem)
  1572.      pointer puuconf;
  1573.      const char *zlogin;
  1574.      struct sconnection *qconn;
  1575.      const char **pzsystem;
  1576. {
  1577.   long istart_time;
  1578.   const char *zport;
  1579.   struct uuconf_port *qport;
  1580.   struct uuconf_port sport;
  1581.   int iuuconf;
  1582.   struct uuconf_dialer *qdialer;
  1583.   struct uuconf_dialer sdialer;
  1584.   boolean ftcp_port;
  1585.   char *zsend, *zspace;
  1586.   boolean fret;
  1587.   char *zstr;
  1588.   struct uuconf_system ssys;
  1589.   const struct uuconf_system *qsys;
  1590.   const struct uuconf_system *qany;
  1591.   char *zloc;
  1592.   struct sstatus sstat;
  1593.   boolean fgotseq, fgotn;
  1594.   int i;
  1595.   char *zlog;
  1596.   char *zgrade;
  1597.  
  1598.   if (pzsystem != NULL)
  1599.     *pzsystem = NULL;
  1600.  
  1601.   ulog (LOG_NORMAL, "Incoming call (login %s port %s)", zlogin,
  1602.     zLdevice == NULL ? (char *) "unknown" : zLdevice);
  1603.  
  1604.   istart_time = ixsysdep_time ((long *) NULL);
  1605.  
  1606.   /* Figure out protocol parameters determined by the port.  If no
  1607.      port was specified we're reading standard input, so try to get
  1608.      the port name and read information from the port file.  We only
  1609.      use the port information to get protocol parameters; we don't
  1610.      want to start treating the port as though it were a modem, for
  1611.      example.  */
  1612.   if (qconn->qport != NULL)
  1613.     {
  1614.       qport = qconn->qport;
  1615.       zport = qport->uuconf_zname;
  1616.       ftcp_port = FALSE;
  1617.     }
  1618.   else
  1619.     {
  1620.       zport = zsysdep_port_name (&ftcp_port);
  1621.       if (zport == NULL)
  1622.     {
  1623.       qport = NULL;
  1624.       zport = "unknown";
  1625.     }
  1626.       else
  1627.     {
  1628.       iuuconf = uuconf_find_port (puuconf, zport, (long) 0, (long) 0,
  1629.                       (int (*) P((struct uuconf_port *,
  1630.                           pointer pinfo))) NULL,
  1631.                       (pointer) NULL,
  1632.                       &sport);
  1633.       if (iuuconf == UUCONF_NOT_FOUND)
  1634.         qport = NULL;
  1635.       else if (iuuconf != UUCONF_SUCCESS)
  1636.         {
  1637.           ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  1638.           return FALSE;
  1639.         }
  1640.       else
  1641.         qport = &sport;
  1642.     }
  1643.     }
  1644.  
  1645.   /* If we've managed to figure out that this is a modem port, now try
  1646.      to get protocol parameters from the dialer.  */
  1647.   qdialer = NULL;
  1648.   if (qport != NULL)
  1649.     {
  1650.       if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM)
  1651.     {
  1652.       if (qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL)
  1653.         {
  1654.           const char *zdialer;
  1655.  
  1656.           zdialer = qport->uuconf_u.uuconf_smodem.uuconf_pzdialer[0];
  1657.           iuuconf = uuconf_dialer_info (puuconf, zdialer, &sdialer);
  1658.           if (iuuconf == UUCONF_SUCCESS)
  1659.         qdialer = &sdialer;
  1660.         }
  1661.       else
  1662.         qdialer = qport->uuconf_u.uuconf_smodem.uuconf_qdialer;
  1663.     }      
  1664.       else if (qport->uuconf_ttype == UUCONF_PORTTYPE_TCP
  1665.            || (qport->uuconf_ttype == UUCONF_PORTTYPE_TLI
  1666.            && (qport->uuconf_ireliable
  1667.                & UUCONF_RELIABLE_SPECIFIED) == 0))
  1668.     ftcp_port = TRUE;
  1669.     }
  1670.  
  1671.   sDaemon.puuconf = puuconf;
  1672.   sDaemon.qsys = NULL;
  1673.   sDaemon.zlocalname = NULL;
  1674.   sDaemon.qconn = qconn;
  1675.   sDaemon.qproto = NULL;
  1676.   sDaemon.clocal_size = -1;
  1677.   sDaemon.cremote_size = -1;
  1678.   sDaemon.cmax_ever = -2;
  1679.   sDaemon.cmax_receive = -1;
  1680.   sDaemon.ifeatures = 0;
  1681.   sDaemon.frequest_hangup = FALSE;
  1682.   sDaemon.fhangup_requested = FALSE;
  1683.   sDaemon.fhangup = FALSE;
  1684.   sDaemon.fmaster = FALSE;
  1685.   sDaemon.fcaller = FALSE;
  1686.   sDaemon.ireliable = 0;
  1687.   sDaemon.bgrade = UUCONF_GRADE_LOW;
  1688.  
  1689.   /* Get the local name to use.  If uuconf_login_localname returns a
  1690.      value, it is not always freed up, although it should be.  */
  1691.   iuuconf = uuconf_login_localname (puuconf, zlogin, &zloc);
  1692.   if (iuuconf == UUCONF_SUCCESS)
  1693.     sDaemon.zlocalname = zloc;
  1694.   else if (iuuconf == UUCONF_NOT_FOUND)
  1695.     {
  1696.       sDaemon.zlocalname = zsysdep_localname ();
  1697.       if (sDaemon.zlocalname == NULL)
  1698.     return FALSE;
  1699.     }
  1700.   else
  1701.     {
  1702.       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  1703.       return FALSE;
  1704.     }
  1705.  
  1706.   /* Tell the remote system who we are.   */
  1707.   zsend = zbufalc (strlen (sDaemon.zlocalname) + sizeof "Shere=");
  1708.   sprintf (zsend, "Shere=%s", sDaemon.zlocalname);
  1709.   fret = fsend_uucp_cmd (qconn, zsend);
  1710.   ubuffree (zsend);
  1711.   if (! fret)
  1712.     return FALSE;
  1713.  
  1714.   zstr = zget_uucp_cmd (qconn, TRUE);
  1715.   if (zstr == NULL)
  1716.     return FALSE;
  1717.  
  1718.   if (zstr[0] != 'S')
  1719.     {
  1720.       ulog (LOG_ERROR, "Bad introduction string");
  1721.       ubuffree (zstr);
  1722.       return FALSE;
  1723.     }
  1724.  
  1725.   zspace = strchr (zstr, ' ');
  1726.   if (zspace != NULL)
  1727.     *zspace = '\0';
  1728.  
  1729.   iuuconf = uuconf_system_info (puuconf, zstr + 1, &ssys);
  1730.   if (iuuconf == UUCONF_NOT_FOUND)
  1731.     {
  1732.       char *zscript;
  1733.  
  1734.       /* Run the remote.unknown script, if appropriate.  */
  1735.       iuuconf = uuconf_remote_unknown (puuconf, &zscript);
  1736.       if (iuuconf == UUCONF_SUCCESS)
  1737.     {
  1738.       if (! fsysdep_unknown_caller (zscript, zstr + 1))
  1739.         {
  1740.           xfree ((pointer) zscript);
  1741.           (void) fsend_uucp_cmd (qconn, "RYou are unknown to me");
  1742.           ubuffree (zstr);
  1743.           return FALSE;
  1744.         }
  1745.       xfree ((pointer) zscript);
  1746.     }
  1747.       else if (iuuconf != UUCONF_NOT_FOUND)
  1748.     {
  1749.       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  1750.       ubuffree (zstr);
  1751.       return FALSE;
  1752.     }
  1753.  
  1754.       if (! funknown_system (puuconf, zstr + 1, &ssys))
  1755.     {
  1756.       (void) fsend_uucp_cmd (qconn, "RYou are unknown to me");
  1757.       ulog (LOG_ERROR, "Call from unknown system %s", zstr + 1);
  1758.       ubuffree (zstr);
  1759.       return FALSE;
  1760.     }
  1761.     }
  1762.   else if (iuuconf != UUCONF_SUCCESS)
  1763.     {
  1764.       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  1765.       ubuffree (zstr);
  1766.       return FALSE;
  1767.     }
  1768.  
  1769.   qany = NULL;
  1770.   for (qsys = &ssys; qsys != NULL; qsys = qsys->uuconf_qalternate)
  1771.     {
  1772.       if (! qsys->uuconf_fcalled)
  1773.     continue;
  1774.  
  1775.       if (qsys->uuconf_zcalled_login == NULL
  1776.       || strcmp (qsys->uuconf_zcalled_login, "ANY") == 0)
  1777.     {
  1778.       if (qany == NULL)
  1779.         qany = qsys;
  1780.     }
  1781.       else if (strcmp (qsys->uuconf_zcalled_login, zlogin) == 0)
  1782.     break;
  1783.     }
  1784.  
  1785.   if (qsys == NULL && qany != NULL)
  1786.     {
  1787.       iuuconf = uuconf_validate (puuconf, qany, zlogin);
  1788.       if (iuuconf == UUCONF_SUCCESS)
  1789.     qsys = qany;
  1790.       else if (iuuconf != UUCONF_NOT_FOUND)
  1791.     {
  1792.       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  1793.       ubuffree (zstr);
  1794.       return FALSE;
  1795.     }
  1796.     }
  1797.  
  1798.   if (qsys == NULL)
  1799.     {
  1800.       (void) fsend_uucp_cmd (qconn, "RLOGIN");
  1801.       ulog (LOG_ERROR, "System %s used wrong login name %s",
  1802.         zstr + 1, zlogin);
  1803.       ubuffree (zstr);
  1804.       return FALSE;
  1805.     }
  1806.  
  1807.   sDaemon.qsys = qsys;
  1808.  
  1809.   if (pzsystem != NULL)
  1810.     *pzsystem = zbufcpy (qsys->uuconf_zname);
  1811.  
  1812.   ulog_system (qsys->uuconf_zname);
  1813.  
  1814. #if DEBUG > 1
  1815.   if (qsys->uuconf_zdebug != NULL)
  1816.     iDebug |= idebug_parse (qsys->uuconf_zdebug);
  1817. #endif
  1818.  
  1819.   /* See if we are supposed to call the system back.  This will queue
  1820.      up an empty command.  It would be better to actually call back
  1821.      directly at this point as well.  */
  1822.   if (qsys->uuconf_fcallback)
  1823.     {
  1824.       (void) fsend_uucp_cmd (qconn, "RCB");
  1825.       ulog (LOG_NORMAL, "Will call back");
  1826.  
  1827.       /* Clear any existing status.  */
  1828.       sstat.ttype = STATUS_COMPLETE;
  1829.       sstat.cretries = 0;
  1830.       sstat.ilast = ixsysdep_time ((long *) NULL);
  1831.       sstat.cwait = 0;
  1832.       (void) fsysdep_set_status (qsys, &sstat);
  1833.  
  1834.       ubuffree (zsysdep_spool_commands (qsys, UUCONF_GRADE_HIGH, 0,
  1835.                     (const struct scmd *) NULL));
  1836.       ubuffree (zstr);
  1837.       return TRUE;
  1838.     }
  1839.  
  1840.   /* We only permit one call at a time from a remote system.  Lock it.  */
  1841.   if (! fsysdep_lock_system (qsys))
  1842.     {
  1843.       (void) fsend_uucp_cmd (qconn, "RLCK");
  1844.       ulog (LOG_ERROR, "System already locked");
  1845.       ubuffree (zstr);
  1846.       return FALSE;
  1847.     }
  1848.   sLocked_system = *qsys;
  1849.   fLocked_system = TRUE;
  1850.  
  1851.   /* Set the system status.  We don't care what the status was before.
  1852.      We also don't want to kill the conversation just because we can't
  1853.      output the .Status file, so we ignore any errors.  */
  1854.   sstat.ttype = STATUS_TALKING;
  1855.   sstat.cretries = 0;
  1856.   sstat.ilast = ixsysdep_time ((long *) NULL);
  1857.   sstat.cwait = 0;
  1858.   (void) fsysdep_set_status (qsys, &sstat);
  1859.  
  1860.   /* Check the arguments of the remote system, if any.  */
  1861.   fgotseq = FALSE;
  1862.   fgotn = FALSE;
  1863.   if (zspace != NULL)
  1864.     {
  1865.       char **paz;
  1866.       char **pzset;
  1867.  
  1868.       ++zspace;
  1869.  
  1870.       /* Break the introduction line up into arguments.  */
  1871.       paz = (char **) xmalloc ((strlen (zspace) / 2 + 2) * sizeof (char *));
  1872.       pzset = paz;
  1873.       *pzset++ = NULL;
  1874.       while (TRUE)
  1875.     {
  1876.       while (*zspace != '\0' && isspace (BUCHAR (*zspace)))
  1877.         ++zspace;
  1878.       if (*zspace == '\0')
  1879.         break;
  1880.       *pzset++ = zspace;
  1881.       ++zspace;
  1882.       while (*zspace != '\0' && ! isspace (BUCHAR (*zspace)))
  1883.         ++zspace;
  1884.       if (*zspace == '\0')
  1885.         break;
  1886.       *zspace++ = '\0';
  1887.     }
  1888.  
  1889.       if (pzset != paz + 1)
  1890.     {
  1891.       int iopt;
  1892.  
  1893.       *pzset = NULL;
  1894.  
  1895.       /* We are going to use getopt to parse the arguments.  We
  1896.          must clear optind to force getopt to reinitialize, and
  1897.          clear opterr to prevent getopt from printing an error
  1898.          message.  This approach assumes we are using the GNU
  1899.          getopt, which is distributed with the program anyhow.  */
  1900.       optind = 0;
  1901.       opterr = 0;
  1902.       
  1903.       while ((iopt = getopt (pzset - paz, paz,
  1904.                  "N::p:Q:RU:v:x:")) != EOF)
  1905.         {
  1906.           long iseq;
  1907.           long c;
  1908.           char b;
  1909.           int iwant;
  1910.  
  1911.           switch (iopt)
  1912.         {
  1913.         case 'N':
  1914.           /* This is used to indicate support for Taylor UUCP
  1915.              extensions.  An plain -N mean support for size
  1916.              negotiation.  If -N is followed by a number (with
  1917.              no intervening space), the number is a bit field
  1918.              of feature flags as defined in trans.h.  Note
  1919.              that the argument may start with 0x for hex or 0
  1920.              for octal.  */
  1921.           fgotn = TRUE;
  1922.           if (optarg == NULL)
  1923.             sDaemon.ifeatures |= FEATURE_SIZES | FEATURE_V103;
  1924.           else
  1925.             sDaemon.ifeatures |= (int) strtol (optarg,
  1926.                                (char **) NULL,
  1927.                                0);
  1928.           break;
  1929.  
  1930.         case 'p':
  1931.           /* The argument is the lowest grade of work the
  1932.              local system should send.  */
  1933.           if (UUCONF_GRADE_LEGAL (optarg[0]))
  1934.             sDaemon.bgrade = optarg[0];
  1935.           break;
  1936.  
  1937.         case 'Q':
  1938.           /* The conversation sequence number.  */
  1939.           iseq = strtol (optarg, (char **) NULL, 10);
  1940.           if (qsys->uuconf_fsequence
  1941.               && iseq != ixsysdep_get_sequence (qsys))
  1942.             {
  1943.               (void) fsend_uucp_cmd (qconn, "RBADSEQ");
  1944.               ulog (LOG_ERROR, "Out of sequence call rejected");
  1945.               sstat.ttype = STATUS_FAILED;
  1946.               (void) fsysdep_set_status (qsys, &sstat);
  1947.               xfree ((pointer) paz);
  1948.               ubuffree (zstr);
  1949.               return FALSE;
  1950.             }
  1951.           fgotseq = TRUE;
  1952.           break;
  1953.  
  1954.         case 'R':
  1955.           /* The remote system supports file restart.  */
  1956.           sDaemon.ifeatures |= FEATURE_RESTART;
  1957.           break;
  1958.  
  1959.         case 'U':
  1960.           /* The maximum file size the remote system is
  1961.              prepared to received, in blocks where each block
  1962.              is 512 bytes.  */
  1963.           c = strtol (optarg, (char **) NULL, 0);
  1964.           if (c > 0 && c < LONG_MAX / (long) 512)
  1965.             sDaemon.cmax_receive = c * (long) 512;
  1966.           break;
  1967.  
  1968.         case 'v':
  1969.           /* -vgrade=X can be used to set the lowest grade of
  1970.              work the local system should send.  */
  1971.           if (strncmp (optarg, "grade=", sizeof "grade=" - 1) == 0)
  1972.             {
  1973.               b = optarg[sizeof "grade=" - 1];
  1974.               if (UUCONF_GRADE_LEGAL (b))
  1975.             sDaemon.bgrade = b;
  1976.             }
  1977.           break;
  1978.  
  1979.         case 'x':
  1980.           iwant = (int) strtol (optarg, (char **) NULL, 10);
  1981. #if DEBUG > 1
  1982.           if (iwant <= 9)
  1983.             iwant = (1 << iwant) - 1;
  1984.           if (qsys->uuconf_zmax_remote_debug != NULL)
  1985.             iwant &= idebug_parse (qsys->uuconf_zmax_remote_debug);
  1986.           if ((iDebug | iwant) != iDebug)
  1987.             {
  1988.               iDebug |= iwant;
  1989.               ulog (LOG_NORMAL, "Setting debugging mode to 0%o",
  1990.                 iDebug);
  1991.             }
  1992. #endif
  1993.           break;
  1994.  
  1995.         default:
  1996.           break;
  1997.         }
  1998.         }
  1999.     }
  2000.  
  2001.       xfree ((pointer) paz);
  2002.     }
  2003.  
  2004.   ubuffree (zstr);
  2005.  
  2006.   if (qsys->uuconf_fsequence && ! fgotseq)
  2007.     {
  2008.       (void) fsend_uucp_cmd (qconn, "RBADSEQ");
  2009.       ulog (LOG_ERROR, "No sequence number (call rejected)");
  2010.       sstat.ttype = STATUS_FAILED;
  2011.       (void) fsysdep_set_status (qsys, &sstat);
  2012.       return FALSE;
  2013.     }
  2014.  
  2015.   /* We recognized the system, and the sequence number (if any) was
  2016.      OK.  Send an ROK, and send a list of protocols.  If we got the -N
  2017.      switch, send ROKN to confirm it; if the -N switch was followed by
  2018.      a feature bitfield, return our own feature bitfield.  */
  2019.   {
  2020.     char ab[20];
  2021.     const char *zreply;
  2022.  
  2023.     if (! fgotn)
  2024.       {
  2025.     if ((sDaemon.ifeatures & FEATURE_RESTART) == 0)
  2026.       zreply = "ROK";
  2027.     else
  2028.       {
  2029.         /* We got -R without -N, so assume that this is SVR4 UUCP.
  2030.            SVR4 UUCP expects ROK -R to signal support for file
  2031.            restart.  */
  2032.         sDaemon.ifeatures |= FEATURE_SVR4 | FEATURE_SIZES;
  2033.         zreply = "ROK -R";
  2034.       }
  2035.       }
  2036.     else if ((sDaemon.ifeatures & FEATURE_V103) != 0)
  2037.       zreply = "ROKN";
  2038.     else
  2039.       {
  2040.     sprintf (ab, "ROKN0%o",
  2041.          (unsigned int) (FEATURE_SIZES
  2042.                  | FEATURE_EXEC
  2043.                  | FEATURE_RESTART));
  2044.     zreply = ab;
  2045.       }
  2046.     if (! fsend_uucp_cmd (qconn, zreply))
  2047.       {
  2048.     sstat.ttype = STATUS_FAILED;
  2049.     (void) fsysdep_set_status (qsys, &sstat);
  2050.     return FALSE;
  2051.       }
  2052.   }
  2053.  
  2054.   /* Determine the reliability of the connection based on the
  2055.      reliability of the port and the dialer.  If we have no
  2056.      information, default to a reliable eight-bit full-duplex
  2057.      connection.  */
  2058.   if (ftcp_port)
  2059.     sDaemon.ireliable = (UUCONF_RELIABLE_SPECIFIED
  2060.              | UUCONF_RELIABLE_ENDTOEND
  2061.              | UUCONF_RELIABLE_RELIABLE
  2062.              | UUCONF_RELIABLE_EIGHT
  2063.              | UUCONF_RELIABLE_FULLDUPLEX);
  2064.   else
  2065.     {
  2066.       if (qport != NULL
  2067.       && (qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
  2068.     sDaemon.ireliable = qport->uuconf_ireliable;
  2069.       if (qdialer != NULL
  2070.       && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
  2071.     {
  2072.       if (sDaemon.ireliable != 0)
  2073.         sDaemon.ireliable &= qdialer->uuconf_ireliable;
  2074.       else
  2075.         sDaemon.ireliable = qdialer->uuconf_ireliable;
  2076.     }
  2077.       if (sDaemon.ireliable == 0)
  2078.     sDaemon.ireliable = (UUCONF_RELIABLE_RELIABLE
  2079.                  | UUCONF_RELIABLE_EIGHT
  2080.                  | UUCONF_RELIABLE_FULLDUPLEX
  2081.                  | UUCONF_RELIABLE_SPECIFIED);
  2082.     }
  2083.  
  2084.   if (qsys->uuconf_zprotocols != NULL ||
  2085.       (qport != NULL && qport->uuconf_zprotocols != NULL))
  2086.     {
  2087.       const char *zprotos;
  2088.  
  2089.       if (qsys->uuconf_zprotocols != NULL)
  2090.     zprotos = qsys->uuconf_zprotocols;
  2091.       else
  2092.     zprotos = qport->uuconf_zprotocols;
  2093.       zsend = zbufalc (strlen (zprotos) + 2);
  2094.       sprintf (zsend, "P%s", zprotos);
  2095.     }
  2096.   else
  2097.     {
  2098.       char *zset;
  2099.  
  2100.       zsend = zbufalc (CPROTOCOLS + 2);
  2101.       zset = zsend;
  2102.       *zset++ = 'P';
  2103.  
  2104.       /* If the system did not specify a list of protocols, we want
  2105.      only protocols that match the known reliability of the dialer
  2106.      and the port.  */
  2107.       for (i = 0; i < CPROTOCOLS; i++)
  2108.     {
  2109.       int ipr;
  2110.  
  2111.       ipr = asProtocols[i].ireliable;
  2112.       if ((ipr & sDaemon.ireliable) != ipr)
  2113.         continue;
  2114.       *zset++ = asProtocols[i].bname;
  2115.     }
  2116.       *zset = '\0';
  2117.     }
  2118.  
  2119.   fret = fsend_uucp_cmd (qconn, zsend);
  2120.   ubuffree (zsend);
  2121.   if (! fret)
  2122.     {
  2123.       sstat.ttype = STATUS_FAILED;
  2124.       (void) fsysdep_set_status (qsys, &sstat);
  2125.       return FALSE;
  2126.     }
  2127.     
  2128.   /* The master will now send back the selected protocol.  */
  2129.   zstr = zget_uucp_cmd (qconn, TRUE);
  2130.   if (zstr == NULL)
  2131.     {
  2132.       sstat.ttype = STATUS_FAILED;
  2133.       (void) fsysdep_set_status (qsys, &sstat);
  2134.       return FALSE;
  2135.     }
  2136.  
  2137.   if (zstr[0] != 'U' || zstr[2] != '\0')
  2138.     {
  2139.       ulog (LOG_ERROR, "Bad protocol response string");
  2140.       sstat.ttype = STATUS_FAILED;
  2141.       (void) fsysdep_set_status (qsys, &sstat);
  2142.       ubuffree (zstr);
  2143.       return FALSE;
  2144.     }
  2145.  
  2146.   if (zstr[1] == 'N')
  2147.     {
  2148.       ulog (LOG_ERROR, "No supported protocol");
  2149.       sstat.ttype = STATUS_FAILED;
  2150.       (void) fsysdep_set_status (qsys, &sstat);
  2151.       ubuffree (zstr);
  2152.       return FALSE;
  2153.     }
  2154.  
  2155.   for (i = 0; i < CPROTOCOLS; i++)
  2156.     if (asProtocols[i].bname == zstr[1])
  2157.       break;
  2158.  
  2159.   ubuffree (zstr);
  2160.  
  2161.   if (i >= CPROTOCOLS)
  2162.     {
  2163.       ulog (LOG_ERROR, "No supported protocol");
  2164.       sstat.ttype = STATUS_FAILED;
  2165.       (void) fsysdep_set_status (qsys, &sstat);
  2166.       return FALSE;
  2167.     }
  2168.  
  2169.   sDaemon.qproto = &asProtocols[i];
  2170.  
  2171.   /* Run the chat script for when a call is received.  */
  2172.   if (! fchat (qconn, puuconf, &qsys->uuconf_scalled_chat, qsys,
  2173.            (const struct uuconf_dialer *) NULL, (const char *) NULL,
  2174.            FALSE, zport, iconn_baud (qconn)))
  2175.     {
  2176.       sstat.ttype = STATUS_FAILED;
  2177.       sstat.ilast = ixsysdep_time ((long *) NULL);
  2178.       (void) fsysdep_set_status (qsys, &sstat);
  2179.       return FALSE;
  2180.     }
  2181.  
  2182.   /* Run any protocol parameter commands.  */
  2183.   if (sDaemon.qproto->qcmds != NULL)
  2184.     {
  2185.       if (qsys->uuconf_qproto_params != NULL)
  2186.     uapply_proto_params (puuconf, sDaemon.qproto->bname,
  2187.                  sDaemon.qproto->qcmds,
  2188.                  qsys->uuconf_qproto_params);
  2189.       if (qport != NULL
  2190.       && qport->uuconf_qproto_params != NULL)
  2191.     uapply_proto_params (puuconf, sDaemon.qproto->bname,
  2192.                  sDaemon.qproto->qcmds,
  2193.                  qport->uuconf_qproto_params);
  2194.       if (qdialer != NULL
  2195.       && qdialer->uuconf_qproto_params != NULL)
  2196.     uapply_proto_params (puuconf, sDaemon.qproto->bname,
  2197.                  sDaemon.qproto->qcmds,
  2198.                  qdialer->uuconf_qproto_params);
  2199.     }
  2200.  
  2201.   /* We don't need the dialer information any more.  */
  2202.   if (qdialer == &sdialer)
  2203.     (void) uuconf_dialer_free (puuconf, &sdialer);
  2204.  
  2205.   /* Get any jobs queued for the system, and turn on the selected
  2206.      protocol.  */
  2207.   if (! fqueue (&sDaemon, (boolean *) NULL)
  2208.       || ! (*sDaemon.qproto->pfstart) (&sDaemon, &zlog))
  2209.     {
  2210.       uclear_queue (&sDaemon);
  2211.       sstat.ttype = STATUS_FAILED;
  2212.       sstat.ilast = ixsysdep_time ((long *) NULL);
  2213.       (void) fsysdep_set_status (qsys, &sstat);
  2214.       return FALSE;
  2215.     }
  2216.  
  2217.   if (zlog == NULL)
  2218.     {
  2219.       zlog = zbufalc (sizeof "protocol ''" + 1);
  2220.       sprintf (zlog, "protocol '%c'", sDaemon.qproto->bname);
  2221.     }
  2222.  
  2223.   zgrade = zbufalc (sizeof "grade  " + 1);
  2224.   if (sDaemon.bgrade == UUCONF_GRADE_LOW)
  2225.     *zgrade = '\0';
  2226.   else
  2227.     sprintf (zgrade, "grade %c ", sDaemon.bgrade);
  2228.  
  2229.   /* If we are using HAVE_HDB_LOGGING, then the previous ``incoming
  2230.      call'' message went to the general log, since we didn't know the
  2231.      system name at that point.  In that case, we repeat the port and
  2232.      login names.  */
  2233. #if HAVE_HDB_LOGGING
  2234.   ulog (LOG_NORMAL, "Handshake successful (login %s port %s %s%s)",
  2235.     zlogin,
  2236.     zLdevice == NULL ? "unknown" : zLdevice,
  2237.     zgrade, zlog);
  2238. #else /* ! HAVE_HDB_LOGGING */
  2239.   ulog (LOG_NORMAL, "Handshake successful (%s%s)", zgrade, zlog);
  2240. #endif /* ! HAVE_HDB_LOGGING */
  2241.  
  2242.   ubuffree (zlog);
  2243.   ubuffree (zgrade);
  2244.  
  2245.   {
  2246.     long iend_time;
  2247.  
  2248.     fret = floop (&sDaemon);
  2249.  
  2250.     /* Hangup.  As the answerer, we send seven O's and expect to
  2251.        receive six O's.  We send the seven O's twice to help the other
  2252.        side.  We don't worry about errors here.  */
  2253.     if (fsend_uucp_cmd (qconn, "OOOOOOO")
  2254.     && fsend_uucp_cmd (qconn, "OOOOOOO"))
  2255.       {
  2256.     int fdone;
  2257.  
  2258.     /* We look for the remote hangup string to ensure that the
  2259.        modem has sent out our hangup string.  This is only
  2260.        necessary because some versions of UUCP complain if they
  2261.        don't get the hangup string.  We look for the string
  2262.        several times because supposedly some implementations send
  2263.        some garbage after the last packet but before the hangup
  2264.        string.  */
  2265.     for (i = 0; i < 25; i++)
  2266.       {
  2267.         zstr = zget_uucp_cmd (qconn, FALSE);
  2268.         if (zstr == NULL)
  2269.           break;
  2270.         fdone = strstr (zstr, "OOOOOO") != NULL;
  2271.         ubuffree (zstr);
  2272.         if (fdone)
  2273.           break;
  2274.       }
  2275.       }
  2276.  
  2277.     iend_time = ixsysdep_time ((long *) NULL);
  2278.  
  2279.     ulog (LOG_NORMAL, "Call complete (%ld seconds)",
  2280.       iend_time - istart_time);
  2281.  
  2282.     uclear_queue (&sDaemon);
  2283.  
  2284.     if (fret)
  2285.       sstat.ttype = STATUS_COMPLETE;
  2286.     else
  2287.       sstat.ttype = STATUS_FAILED;
  2288.     sstat.ilast = iend_time;
  2289.     (void) fsysdep_set_status (qsys, &sstat);
  2290.  
  2291.     (void) uuconf_system_free (puuconf, &ssys);
  2292.     if (qport == &sport)
  2293.       (void) uuconf_port_free (puuconf, &sport);
  2294.     xfree ((pointer) zloc);
  2295.  
  2296.     return fret;
  2297.   }
  2298. }
  2299.  
  2300. /* Apply protocol parameters, once we know the protocol.  */
  2301.  
  2302. static void
  2303. uapply_proto_params (puuconf, bproto, qcmds, pas)
  2304.      pointer puuconf;
  2305.      int bproto;
  2306.      struct uuconf_cmdtab *qcmds;
  2307.      struct uuconf_proto_param *pas;
  2308. {
  2309.   struct uuconf_proto_param *qp;
  2310.  
  2311.   for (qp = pas; qp->uuconf_bproto != '\0'; qp++)
  2312.     {
  2313.       if (qp->uuconf_bproto == bproto)
  2314.     {
  2315.       struct uuconf_proto_param_entry *qe;
  2316.  
  2317.       for (qe = qp->uuconf_qentries; qe->uuconf_cargs > 0; qe++)
  2318.         {
  2319.           int iuuconf;
  2320.  
  2321.           iuuconf = uuconf_cmd_args (puuconf, qe->uuconf_cargs,
  2322.                      qe->uuconf_pzargs, qcmds,
  2323.                      (pointer) NULL,
  2324.                      (uuconf_cmdtabfn) NULL, 0,
  2325.                      (pointer) NULL);
  2326.           if (UUCONF_ERROR_VALUE (iuuconf) != UUCONF_SUCCESS)
  2327.         {
  2328.           ulog (LOG_ERROR, "Error in %c protocol parameters",
  2329.             bproto);
  2330.           ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
  2331.         }
  2332.         }
  2333.  
  2334.       break;
  2335.     }
  2336.     }
  2337. }
  2338.  
  2339. /* Send a string to the other system beginning with a DLE
  2340.    character and terminated with a null byte.  This is only
  2341.    used when no protocol is in force.  */
  2342.  
  2343. static boolean
  2344. fsend_uucp_cmd (qconn, z)
  2345.      struct sconnection *qconn;
  2346.      const char *z;
  2347. {
  2348.   size_t cwrite;
  2349.   char *zalc;
  2350.   boolean fret;
  2351.  
  2352.   DEBUG_MESSAGE1 (DEBUG_HANDSHAKE, "fsend_uucp_cmd: Sending \"%s\"", z);
  2353.  
  2354.   cwrite = strlen (z) + 2;
  2355.  
  2356.   zalc = zbufalc (cwrite);
  2357.   zalc[0] = '\020';
  2358.   memcpy (zalc + 1, z, cwrite - 1);
  2359.  
  2360.   fret = fconn_write (qconn, zalc, cwrite);
  2361.   ubuffree (zalc);
  2362.   return fret;
  2363. }
  2364.  
  2365. /* Get a UUCP command beginning with a DLE character and ending with a
  2366.    null byte.  This is only used when no protocol is in force.  This
  2367.    implementation has the potential of being seriously slow.  It also
  2368.    doesn't have any real error recovery.  The frequired argument is
  2369.    passed as TRUE if we need the string; we don't care that much if
  2370.    we're closing down the connection anyhow.  */
  2371.  
  2372. #define CTIMEOUT (120)
  2373. #define CSHORTTIMEOUT (10)
  2374. #define CINCREMENT (100)
  2375.  
  2376. static char *
  2377. zget_uucp_cmd (qconn, frequired)
  2378.      struct sconnection *qconn;
  2379.      boolean frequired;
  2380. {
  2381.   char *zalc;
  2382.   size_t calc;
  2383.   size_t cgot;
  2384.   boolean fintro;
  2385.   long iendtime;
  2386.   int ctimeout;
  2387. #if DEBUG > 1
  2388.   int cchars;
  2389.   int iolddebug;
  2390. #endif
  2391.  
  2392.   iendtime = ixsysdep_time ((long *) NULL);
  2393.   if (frequired)
  2394.     iendtime += CTIMEOUT;
  2395.   else
  2396.     iendtime += CSHORTTIMEOUT;
  2397.  
  2398. #if DEBUG > 1
  2399.   cchars = 0;
  2400.   iolddebug = iDebug;
  2401.   if (FDEBUGGING (DEBUG_HANDSHAKE))
  2402.     {
  2403.       ulog (LOG_DEBUG_START, "zget_uucp_cmd: Got \"");
  2404.       iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT);
  2405.     }
  2406. #endif
  2407.  
  2408.   zalc = NULL;
  2409.   calc = 0;
  2410.   cgot = 0;
  2411.   fintro = FALSE;
  2412.   while ((ctimeout = (int) (iendtime - ixsysdep_time ((long *) NULL))) > 0)
  2413.     {
  2414.       int b;
  2415.       
  2416.       b = breceive_char (qconn, ctimeout, frequired);
  2417.       /* Now b == -1 on timeout, -2 on error.  */
  2418.       if (b < 0)
  2419.     {
  2420. #if DEBUG > 1
  2421.       if (FDEBUGGING (DEBUG_HANDSHAKE))
  2422.         {
  2423.           ulog (LOG_DEBUG_END, "\" (%s)",
  2424.             b == -1 ? "timeout" : "error");
  2425.           iDebug = iolddebug;
  2426.         }
  2427. #endif
  2428.       if (b == -1 && frequired)
  2429.         ulog (LOG_ERROR, "Timeout");
  2430.       ubuffree (zalc);
  2431.       return NULL;
  2432.     }
  2433.  
  2434.       /* Apparently some systems use parity on these strings, so we
  2435.      strip the parity bit.  This may need to be configurable at
  2436.      some point, although only if system names can have eight bit
  2437.      characters.  */
  2438.       if (! isprint (BUCHAR (b)))
  2439.     b &= 0x7f;
  2440.  
  2441. #if DEBUG > 1
  2442.       if (FDEBUGGING (DEBUG_HANDSHAKE))
  2443.     {
  2444.       char ab[5];
  2445.  
  2446.       ++cchars;
  2447.       if (cchars > 60)
  2448.         {
  2449.           ulog (LOG_DEBUG_END, "\"");
  2450.           ulog (LOG_DEBUG_START, "zget_uucp_cmd: Got \"");
  2451.           cchars = 0;
  2452.         }
  2453.       (void) cdebug_char (ab, b);
  2454.       ulog (LOG_DEBUG_CONTINUE, "%s", ab);
  2455.     }
  2456. #endif
  2457.  
  2458.       if (! fintro)
  2459.     {
  2460.       if (b == '\020')
  2461.         fintro = TRUE;
  2462.       continue;
  2463.     }
  2464.  
  2465.       /* If we see another DLE, something has gone wrong; continue
  2466.      as though this were the first one we saw.  */
  2467.       if (b == '\020')
  2468.     {
  2469.       cgot = 0;
  2470.       continue;
  2471.     }
  2472.  
  2473.       /* Some systems send a trailing \n on the Shere line.  As far as
  2474.      I can tell this line can never contain a \n, so this
  2475.      modification should be safe enough.  */
  2476.       if (b == '\r' || b == '\n')
  2477.     b = '\0';
  2478.  
  2479.       if (cgot >= calc)
  2480.     {
  2481.       char *znew;
  2482.  
  2483.       calc += CINCREMENT;
  2484.       znew = zbufalc (calc);
  2485.       memcpy (znew, zalc, cgot);
  2486.       ubuffree (zalc);
  2487.       zalc = znew;
  2488.     }
  2489.  
  2490.       zalc[cgot] = (char) b;
  2491.       ++cgot;
  2492.  
  2493.       if (b == '\0')
  2494.     {
  2495. #if DEBUG > 1
  2496.       if (FDEBUGGING (DEBUG_HANDSHAKE))
  2497.         {
  2498.           ulog (LOG_DEBUG_END, "\"");
  2499.           iDebug = iolddebug;
  2500.         }
  2501. #endif
  2502.       return zalc;
  2503.     }
  2504.     }
  2505.  
  2506. #if DEBUG > 1
  2507.   if (FDEBUGGING (DEBUG_HANDSHAKE))
  2508.     {
  2509.       ulog (LOG_DEBUG_END, "\" (timeout)");
  2510.       iDebug = iolddebug;
  2511.     }
  2512. #endif
  2513.  
  2514.   ubuffree (zalc);
  2515.  
  2516.   if (frequired)
  2517.     ulog (LOG_ERROR, "Timeout");
  2518.   return NULL;
  2519. }
  2520.  
  2521. /* Read a sequence of characters up to a newline or carriage return, and
  2522.    return the line without the line terminating character.  */
  2523.  
  2524. static char *
  2525. zget_typed_line (qconn)
  2526.      struct sconnection *qconn;
  2527. {
  2528.   char *zalc;
  2529.   size_t calc;
  2530.   size_t cgot;
  2531.  
  2532. #if DEBUG > 1
  2533.   int cchars;
  2534.   int iolddebug;
  2535.  
  2536.   cchars = 0;
  2537.   iolddebug = iDebug;
  2538.   if (FDEBUGGING (DEBUG_CHAT))
  2539.     {
  2540.       ulog (LOG_DEBUG_START, "zget_typed_line: Got \"");
  2541.       iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT);
  2542.     }
  2543. #endif
  2544.  
  2545.   zalc = NULL;
  2546.   calc = 0;
  2547.   cgot = 0;
  2548.   while (TRUE)
  2549.     {
  2550.       int b;
  2551.       
  2552.       b = breceive_char (qconn, CTIMEOUT, FALSE);
  2553.  
  2554.       /* Now b == -1 on timeout, -2 on error.  */
  2555.  
  2556.       if (b == -2 || FGOT_SIGNAL ())
  2557.     {
  2558. #if DEBUG > 1
  2559.       if (FDEBUGGING (DEBUG_CHAT))
  2560.         {
  2561.           ulog (LOG_DEBUG_END, "\" (error)");
  2562.           iDebug = iolddebug;
  2563.         }
  2564. #endif
  2565.       ubuffree (zalc);
  2566.       return NULL;
  2567.     }
  2568.  
  2569.       if (b == -1)
  2570.     continue;
  2571.  
  2572. #if DEBUG > 1
  2573.       if (FDEBUGGING (DEBUG_CHAT))
  2574.     {
  2575.       char ab[5];
  2576.  
  2577.       ++cchars;
  2578.       if (cchars > 60)
  2579.         {
  2580.           ulog (LOG_DEBUG_END, "\"");
  2581.           ulog (LOG_DEBUG_START, "zget_typed_line: Got \"");
  2582.           cchars = 0;
  2583.         }
  2584.       (void) cdebug_char (ab, b);
  2585.       ulog (LOG_DEBUG_CONTINUE, "%s", ab);
  2586.     }
  2587. #endif
  2588.  
  2589.       if (cgot >= calc)
  2590.     {
  2591.       char *znew;
  2592.  
  2593.       calc += CINCREMENT;
  2594.       znew = zbufalc (calc);
  2595.       memcpy (znew, zalc, cgot);
  2596.       ubuffree (zalc);
  2597.       zalc = znew;
  2598.     }
  2599.  
  2600.       if (b == '\r' || b == '\n')
  2601.     b = '\0';
  2602.  
  2603.       zalc[cgot] = (char) b;
  2604.       ++cgot;
  2605.  
  2606.       if (b == '\0')
  2607.     {
  2608. #if DEBUG > 1
  2609.       if (FDEBUGGING (DEBUG_CHAT))
  2610.         {
  2611.           ulog (LOG_DEBUG_END, "\"");
  2612.           iDebug = iolddebug;
  2613.         }
  2614. #endif
  2615.       return zalc;
  2616.     }
  2617.     }
  2618. }
  2619.